import {
	useContext,
	useState,
	useMemo,
	useEffect,
	isValidElement,
	cloneElement,
} from 'react'
import FormContext from '../FormContext'
import Label from './Label.js'
import Message from './Message.js'
function FormItem({
	name,
	children,
	label,
	height = 50,
	labelWidth,
	required = false,
	rules = {},
	trigger = 'onChange',
	validateTrigger = 'onChange',
}) {
	// 1 获取表单实例方法
	const formInstance = useContext(FormContext)
	const { registerValidateFields, dispatch, unRegisterValidate } =
		formInstance
	const [, setState] = useState({})
	// 2.创建一个更新表单方法
	const onStoreChange = useMemo(() => {
		/* 状态管理层 => 通知表单项 */
		const onStoreChange = {
			changeValue() {
				setState({})
			},
		}
		return onStoreChange
	}, [formInstance])
	useEffect(() => {
		/* 注册表单 */
		name &&
			registerValidateFields(name, onStoreChange, { ...rules, required })

		return () => {
			name && unRegisterValidate(name)
		}
	}, [onStoreChange])

	/* 使表单变成可控的 */
	const getControlled = (child) => {
		const megerChildrenProps = { ...child.props }
		if (!name) return megerChildrenProps
		/* 修改表单单元项的值 */
		const handleChange = (e) => {
			const value = e.target.value
			// 设置表单项的值
			dispatch({ type: 'setFieldsValue' }, name, value)
		}
		megerChildrenProps[trigger] = handleChange
		if (required || rules) {
			/* 验证表单单元项的值 */
			megerChildrenProps[validateTrigger] = (e) => {
				/* 当值改变和验证表单 用统一一个事件 */
				if (validateTrigger === trigger) {
					handleChange(e)
				}
				//触发表单验证
				dispatch({ type: 'validateField' }, name)
			}
		}
		// 获取value
		megerChildrenProps.value = dispatch({ type: 'getFieldValue' }, name)
		return megerChildrenProps
	}
	let renderChildren
	// 如果是一个react组件
	if (isValidElement(children)) {
		/* 获取 ｜ 合并 ｜ 转发 */
		renderChildren = cloneElement(children, getControlled(children))
	} else {
		renderChildren = children
	}

	return (
		<Label
			height={height}
			label={label}
			labelWidth={labelWidth}
			required={required}
		>
			{renderChildren}
			<Message
				name={name}
				{...dispatch({ type: 'getFieldmodel' }, name)}
			/>
		</Label>
	)
}
export default FormItem
